using CfgTable;
using Cysharp.Threading.Tasks;
using IQIGame.Onigao.Game;
using NetProtocol.POD;
using System.Collections.Generic;

namespace IQIGame.Onigao.GamePlay
{
    public partial class MainCityRegionCtrl : TModuleController
    {
        public MainCityController mainCityCtrl => parent as MainCityController;
        public MainCitySceneCtrl sceneCtrl { get; private set; }
        public MainCityEntityCtrl entityCtrl { get; private set; }
        public MainCityCameraCtrl cameraCtrl { get; private set; }
        public MainCityGamepadCtrl gamepadCtrl { get; private set; }
        public MainCityNavigationCtrl navigationCtrl { get; private set; }
        public MainCityEffectCtrl effectCtrl { get; private set; }
        public MainCityEntityViewCtrl entityViewCtrl { get; private set; }

        public UILevelInput uiInput { get; private set; }
        public UILightDialog uiLightDialog { get; private set; }

        public CfgRegionInstance cfgRegion { get; private set; }
        public CfgScene cfgScene { get; private set; }
        public MainCitySceneConfig sceneGameplayConfig { get; private set; }
        public bool isSceneReady { get; private set; }
        public DynMainCityRegion dynRegion { get; private set; }

        public MainCityRegionCtrl()
        {
            sceneCtrl = AddSubController<MainCitySceneCtrl>();
            entityCtrl = AddSubController<MainCityEntityCtrl>();
            cameraCtrl = AddSubController<MainCityCameraCtrl>();
            gamepadCtrl = AddSubController<MainCityGamepadCtrl>();
            navigationCtrl = AddSubController<MainCityNavigationCtrl>();
            effectCtrl = AddSubController<MainCityEffectCtrl>();
            entityViewCtrl = AddSubController<MainCityEntityViewCtrl>();
        }

        protected override void OnModuleGameplayInit()
        {
        }

        protected override void OnSceneLoaded()
        {

        }

        public async UniTask Enter(int regionCid)
        {
            MsgDispatcher.AddListener<BattleEnterPOD>(MsgEventType.BattleView_Start, OnBattleStart);
            MsgDispatcher.AddListener(MsgEventType.BattleView_Exit, OnBattleExit);

            cfgRegion = TableCenter.regionInstance.Get(regionCid);
            cfgScene = TableCenter.scene.Get(cfgRegion.SceneId);
            sceneCtrl.AddFirstPreloadAfterScene(PreLoad);
            //模块玩法初始化完毕Controller事件
            await sceneCtrl.EnterScene();
            DispatchInnerEvent(TControllerEvent.OnSceneLoaded);
            isSceneReady = true;
            MsgDispatcher.Broadcast(MsgEventType.GameplayAreaSceneLoaded);
            await ShowDefaultUI();
        }

        private async UniTask PreLoad()
        {
            var cfgPath = PathConstant.GetSceneGameplayCfg(cfgRegion.GameplayConfig);
            sceneGameplayConfig = await GameplayAreaModularConfigMgr.Instance.LoadModularConfig<MainCitySceneConfig>(cfgPath);

            MainCityRegionData curRegionData = null;
            GameDataCenter.PlayerData.mainCityData?.regions?.TryGetValue(GameplayAreaManager.Instance.curSceneArea.curRegionCid,
                out curRegionData);
            dynRegion = DynMainCityRegion.Create(cfgRegion, sceneGameplayConfig, curRegionData);
        }

        private async UniTask ShowDefaultUI()
        {
            await ManagerCenter.UI.ShowWindowAsync<UIMain>();
            await ManagerCenter.UI.ShowWindowAsync<UIMainFormation>();
            await ManagerCenter.UI.ShowWindowAsync<UILevelInput>();
            await ManagerCenter.UI.ShowWindowAsync<UILightDialog>();

            this.uiInput = ManagerCenter.UI.GetEntityUI<UILevelInput>();
            this.uiLightDialog = ManagerCenter.UI.GetEntityUI<UILightDialog>();

            this.gamepadCtrl.AddJoystickListener();
            await GameScenePlayUtil.ShowEntityTrack();
            NoticeModule.ShowNoticeNoCall(1, cfgRegion.Name);
        }

        private void HideDefaultUI()
        {
            ManagerCenter.UI.CloseWindow<UIMain>();
            ManagerCenter.UI.CloseWindow<UILevelInput>();
            ManagerCenter.UI.CloseWindow<UIMainFormation>();
            ManagerCenter.UI.CloseWindow<UILightDialog>();
            uiInput = null;
            uiLightDialog = null;
            GameScenePlayUtil.HideQuestTrack();
        }

        private void OnBattleStart(BattleEnterPOD pod)
        {
            cameraCtrl.SetCameraActive(false);

            var mainCharacter = entityCtrl.playerAvatarEntity;
            mainCharacter.transform.position = GameGlobalConst.FarEnoughPosition;

            sceneCtrl.SetBaseObjActive(false);

            HideDefaultUI();
        }

        /// <summary>
        /// 战斗结束
        /// 现在暂时是用过BattleModule退出战斗的事件来恢复的
        /// 后面可能要改成通过战斗结算面板来恢复，可以尝试直接挪动派发事件的位置。
        /// </summary>
        private void OnBattleExit()
        {
            cameraCtrl.SetCameraActive(true);

            var mainCharacter = entityCtrl.playerAvatarEntity;
            mainCharacter.transform.position = mainCharacter.unityPosOfData;

            sceneCtrl.SetBaseObjActive(true);

            ShowDefaultUI().Forget();
        }

        /// <summary>
        /// 获取地图需要的实体
        /// </summary>
        /// <param name="result"></param>
        public void GetMapEntites(List<MainCityBaseEntity> result)
        {
            foreach (var entity in entityCtrl.entities.Values)
            {
                result.Add(entity); //临时，都返回
            }
        }

        public void CheckMove(MainCityPlayerAvatarEntity playerAvatar)
        {
            var playerPos = playerAvatar.transform.position;
            //将这一次的实体距离数据刷到上一次，然后再移动。
            //这么做是为了为一些需要判断英雄移动历史的功能提供数据（如是否从某范围内刚好离开）
            playerAvatar.EntityDisNowToPrev();

            //尝试触发移动触发器
            var entitiesInRange = ListPool<MainCityBaseEntity>.Get(); //using entities
            {
                entityCtrl.QTQueryObjects(entitiesInRange, playerPos);
                bool anyExecDone = false;
                for (int i = 0; i < entitiesInRange.Count; i++)
                {
                    var entity = entitiesInRange[i];
                    float sqrDistance = (entity.unityPosOfData - playerPos).sqrMagnitude;
                    if (sqrDistance <= MainCityConst.HeroQuadQueryHalfSize * MainCityConst.HeroQuadQueryHalfSize) //不能超过查询范围
                    {
                        playerAvatar.UpdateEntityDis(entity.id, sqrDistance); //更新这一次的实体距离数据
                    }
                    if (!anyExecDone) //一次只触发一个实体的服务
                    {
                        entity.TryTriggerService(MainCityTriggerType.MoveInRange, out anyExecDone); //移动触发
                    }
                }
                ListPool<MainCityBaseEntity>.Put(entitiesInRange); //release entities
            }
        }

        protected override void OnDispose()
        {
            dynRegion.Release();
            dynRegion = null;
            HideDefaultUI();
            MsgDispatcher.RemoveListener<BattleEnterPOD>(MsgEventType.BattleView_Start, OnBattleStart);
            MsgDispatcher.RemoveListener(MsgEventType.BattleView_Exit, OnBattleExit);
        }
    }
}
